#include "normal.h"

#include <cstdlib>
#include <ctime>
#include <cmath>
#include "enhsimoutput.h"

NormalDistributedRandom::NormalDistributedRandom(float mean, float standard_deviation):
mean_(mean),
standard_deviation_(standard_deviation),
seed_(static_cast<int>(time(0))),
seed2_(0),
used_(-1),
y_(0.0f) {
}

float NormalDistributedRandom::generate() {
	float r1, r2, x;

	if (used_ == -1) {
		used_ = 0;
	}

	if ((used_ % 2) == 0) {
		r1 = uniform(seed_);

		if (r1 == 0.0f) {
			enh::eout << "\n";
			enh::eout << "NormalDistributedRandom: Fatal Error!\n";
			exit(1);
		}

		seed2_ = seed_;
		r2 = uniform(seed2_);

		x = static_cast<float>(sqrt(-2.0 * log(r1)) * cos(2.0 * 3.141592653589793 * r2));
		y_ = static_cast<float>(sqrt(-2.0 * log(r1)) * sin(2.0 * 3.141592653589793 * r2));
	}
	else {
		x = y_;
		seed_ = seed2_;
	}

	++used_;

	return mean_ + standard_deviation_ * x;
}

float NormalDistributedRandom::uniform(int& seed) {
	int k = seed / 127773;
	seed = 16807 * (seed - k * 127773) - k * 2836;

	if (seed < 0) {
		seed = seed + 2147483647;
	}

	return static_cast<float>((seed) * 4.656612875E-10);
}